<template>
    <div 
        v-if="state.isShow"
        ref="editRuleRef" 
        class="edit-rule-container w-full h-full"
        :class="[state.isBlack ? 'balckwrapper' : 'whitewrapper']" 
        :style="rectStyle"
    >
        <SketchRule
            ref="sketchruleRef"
            class="sketch-rule-component"
            :key="state.rendIndex"
            v-model:scale="scale"
            v-model:lock-line="state.lockLine"
            :thick="state.thick"
            :width="canvasBox().width"
            :height="canvasBox().height"
            :show-ruler="state.showRuler"
            :palette="cpuPalette"
            :snaps-obj="state.snapsObj"
            :canvas-width="canvasSize.width"
            :canvas-height="canvasSize.height"
            :panzoom-option="panzoomOption"
            :is-show-refer-line="state.isShowReferLine"
            :lines="state.lines"
            :auto-center="state.autoCenter"
            @on-corner-click="handleCornerClick"
            @zoomchange="zoomchange"
        >
            <template #default>
                <div ref="$app" class="edit-screens" >
                    <context-menu>
                        <div 
                            ref="refSketchRuleBox" 
                            class="canvas"
                            id="canvas"
                            :style="{
                                width: canvasSize.width + 'px',
                                height: canvasSize.height + 'px'
                            }"
                            
                            @mousedown="mousedownHandleUnStop"
                            @drop="drop"
                            @dragenter="handleDragover" 
                            @dragover="handleDragover"
                        > 
                            <slot/>
                        </div>
                        <template #overlay>
                            <div class="menu-list">
                                <a-button 
                                    v-for="(item,index) in menuList"
                                    :key="index"
                                    block 
                                    type="text" 
                                    @click.capture="($event)=>item.fn($event)"
                                >
                                    {{ item.label }}
                                </a-button>
                            </div>
                        </template>
                    </context-menu>
                </div>
            </template>
        </SketchRule>
        <edit-tool :pState="state" @reset-method="resetMethod" @zoom-out-method="zoomOutMethod"/>
    </div>
</template>

<script setup lang="ts">
import { computed, onBeforeMount, onBeforeUnmount, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import SketchRule from 'vue3-sketch-ruler'
import 'vue3-sketch-ruler/lib/style.css'
import { useDataViewStore } from '@/stores/dataview'
import { storeToRefs } from 'pinia'
import { debounce, size, throttle } from 'lodash'
import { useDataViewLayoutStore } from '@/stores/dataviewLayout'
import editTool from '../editTool/edit-tool.vue'
import { useMouseHandle } from '../hooks/useDrag';
import { DragKeyEnum } from '@/const';
import { EditCanvasTypeEnum } from '@/stores/types';
import type { ConfigType } from '@/views/dataview/packages/type';
import { createComponent } from '@/views/dataview/packages';
import type { CreateComponentType } from '@/views/dataview/packages/public/type';
import { setComponentPosition } from '../../../../../../utils/dataview';
import contextMenu from '@/components/context-menu/index.vue'
import { useContextMenu } from '../hooks/useContextMenu'


const {menuList} = useContextMenu()
const {mousedownHandleUnStop} = useMouseHandle()

const dataviewLayoutStore = useDataViewLayoutStore()
const { dataviewLayoutState } = storeToRefs(dataviewLayoutStore)
const dataviewStore = useDataViewStore()
const { dataviewState } = storeToRefs(dataviewStore)
const sketchruleRef = ref()
const editRuleRef = ref<HTMLElement>()
const refSketchRuleBox = ref<HTMLElement>()

const ob = ref<ResizeObserver>()

const state = reactive({
    thick: 20,
    startX: 0,
    startY: 0,
    lines: { h: [], v: [] },
    isShowReferLine: true,
    rendIndex:0,
    lockLine:false,
    showRuler:true,
    isBlack:false,
    snapsObj:{ h: [0, 100, 200], v: [130] }, //吸附刻度线集合
    sketchRuleReDraw:true,
    canvasWidth:1920,
    canvasHeigth:1080,
    autoCenter:true,
    isShow:true
})
// panzoom相关的扩展参数
const panzoomOption = reactive({
    maxScale: 3,
    minScale: 0.3,
    startX: 0,   // 画布距离左边框距离, 如果想自动,那么不要传
    startY: 0,   // 画布距离顶边框距离, 如果想自动,那么不要传
    disablePan: false,
    disableZoom: false,
    contain: 'none', // 'inside' | 'outside' | 'none'
    handleStartEvent: (event:any) => {
        event.preventDefault()
    }
})

const scale = computed({
    get(){
        return dataviewState.value.editCanvas.scale
    },
    set(val){
        dataviewState.value.editCanvas.scale = val
    }
})


const rectStyle = computed(() => {
    return {
        width: `${canvasBox().width}px`,
        height: `${canvasBox().height}px`
    }
})

const cpuPalette = computed(() => {
    return state.isBlack
        ? {
            bgColor: 'transparent',
            hoverBg: '#fff',
            hoverColor: '#000',
            longfgColor: '#BABBBC', // ruler longer mark color
            fontColor: '#DEDEDE', // ruler font color
            shadowColor: '#525252', // ruler shadow color
            lineColor: '#51d6a9',
            borderColor: '#B5B5B5'
        }
        : {
            bgColor: 'transparent',
            lineColor: '#51d6a9',
            lineType: 'dashed'
        }
})


const canvasSize = computed(() => {
    if (dataviewLayoutState.value.layoutContentWidth) {
        // 使用容器宽度的80%作为画布宽度
        const width = Math.floor(dataviewLayoutState.value.layoutContentWidth * 0.90);
        // 计算高度保持16:9的宽高比例
        const height = Math.floor(width * 9 / 16);
        
        return {
            width,
            height
        }
    }
    return {
        width: 1920,
        height: 1080
    }
})

// 锁定
const isLock = computed(()=>{
    const chart = dataviewStore.getSelectComponent()
    return chart ? chart.status.lock : false
})

const selectNum = computed(()=>dataviewState.value.targetChart.selectId.length)

const canvasBox = () => {
    if (dataviewLayoutState.value.layoutContentWidth && dataviewLayoutState.value.layoutContentHeight) {
        let scroll = 0
        return {
            width: dataviewLayoutState.value.layoutContentWidth - scroll,
            height: dataviewLayoutState.value.layoutContentHeight - scroll
        }
    }
    return {
        width: dataviewState.value.editCanvasConfig.width,
        height: dataviewState.value.editCanvasConfig.height
    }
}

const handleCornerClick = () => {
    state.isShowReferLine = !state.isShowReferLine
}

const zoomchange = (detail:any) => {
    handleScale()
}

const handleScale = () => {
    dataviewState.value.componentList.forEach((compInstance:any) => {
        compInstance.attr = Object.assign(compInstance.attr, {

        })
    })
}

const resetMethod = () => {
    if (sketchruleRef.value) {
        sketchruleRef.value.reset()
    }
}

const zoomOutMethod = () => {
    if (sketchruleRef.value) {
        sketchruleRef.value.zoomOut()
    }
}

const drop = async(e:DragEvent) => {
    e.preventDefault()
    // 取出菜单拖拽存储的数据
    const str = e.dataTransfer?.getData(DragKeyEnum.DRAG_KEY)
    if(!str) return
    const config : Exclude<ConfigType,['image']> = JSON.parse(str)
    dataviewStore.setEditCanvas(EditCanvasTypeEnum.IS_CREATE,false)
    if(config.disabled) return //排除禁用创建
    const newComponent:CreateComponentType = await createComponent(config)
    if(config.redirectComponent){
        // 字体图标或者图片配置
    }

    // 设置组件位置并且位于拖拽点居中
    setComponentPosition(
        newComponent,
        e.offsetX - newComponent.attr.w / 2,
        e.offsetY - newComponent.attr.h / 2,
    )

    dataviewStore.addComponnetList(newComponent,false,true)
    dataviewStore.setTargetSelectChart(newComponent.id)
}
const handleDragover = (e:DragEvent) => {
    e.preventDefault()
    e.stopPropagation()
}

const debouncedResize = debounce((e: Event) => {
    // 更新渲染索引触发重新渲染
    // state.rendIndex++
}, 200)



// 屏幕宽度小于一定数值隐藏画布
watch(()=>dataviewLayoutState.value.layoutContentWidth,()=>{
    // @ts-ignore
    if(dataviewLayoutState.value.layoutContentWidth < 50 ){
        state.isShow = false
    }else{
        state.isShow = true
    }
})

onMounted(()=>{
    // 主体画布大小赋值给pinia，用于边界值计算
    // 使用监听器监听画布大小变化,watch无法监听
    if(refSketchRuleBox.value){
        ob.value = new ResizeObserver((entries:any)=>{
            for (const entry of entries) {
                const { width, height } = entry.contentRect;
                dataviewState.value.editCanvasConfig.width = width
                dataviewState.value.editCanvasConfig.height = height
            }
        })
        ob.value.observe(refSketchRuleBox.value)
    }
})


onBeforeMount(() => {
    window.addEventListener('resize', debouncedResize)
})


onUnmounted(() => {
    window.removeEventListener('resize', debouncedResize)
    if(refSketchRuleBox.value){
        ob.value?.unobserve(refSketchRuleBox.value)
    }
})
</script>

<style lang="scss" scoped>
.edit-rule-container {
    overflow: hidden;
    margin: 0 auto;
    background-size: 21px 21px, 21px 21px;
    border: 1px solid #dadadc;
    display: flex;
    justify-content: center;
    align-items: center;
    
    .edit-screens {
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        overflow: hidden;
    }
    
    .canvas {
        width: 100%;
        height: 100%;
        position: relative;
        transform-origin: center center;
        background-color: #f5f7fa;
        // background-color: orange;
        overflow: hidden;
    }
}
:deep(.canvasedit) {
    width: 100%;
    height: 100%;
}
.whitewrapper {
    background-color: #fafafc;
    background-image: linear-gradient(#fafafc 20px, transparent 0),
        linear-gradient(90deg, transparent 20px, #373739 0);
}

.balckwrapper {
    background-color: #18181c;
    background-image: linear-gradient(#18181c 20px, transparent 0),
        linear-gradient(90deg, transparent 20px, #86909c 0);
}
:deep(.sketch-rule-component) {
    position: relative;
    z-index: 1;
}

[data-type="page"] {
    position: relative;
    width: 100%;
    height: 100%;
    background: var(--color-bg-1);
}

.canvas {
    // background-color: #f5f7fa;
    background-color: orange;
}

.btns {
    position: absolute;
    right: 24px;
    bottom: 24px;
    z-index: 3;
    display: flex;
    gap: 8px;

    button {
        padding: 4px 8px;
        border: 1px solid var(--color-border);
        border-radius: 4px;
        background: var(--color-bg-2);
        cursor: pointer;
        
        &:hover {
            background: var(--color-fill-2);
        }
    }
}

.menu-list{
    width: 120px;
    padding: 5px;
    .ant-btn{
        margin-bottom: 5px!important;
        &:last-child{
            margin-bottom: 0!important;
        }
    }
}
</style>